package com.cavy.platform.server.repository.impl;

import com.cavy.platform.server.CavyConfig;
import com.cavy.platform.server.domain.AbstractConfigMap;
import com.cavy.platform.server.repository.ConfigMapRepository;
import com.cavy.platform.server.util.FileUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Repository
public class ConfigMapRepositoryImpl implements ConfigMapRepository {
    public static final String SUFFIX = ".json";
    public static final String FORMAT = "%s-%s" + SUFFIX;
    @Autowired
    private CavyConfig config;

    @Override
    public void save(AbstractConfigMap map) {
        File dataDir = config.getConfigMap().getDataDir();
        File file = new File(dataDir, getMapName(map.getName(), map.getWorkSpace()));
        save(map, file);
    }

    private String getMapName(String name, String workSpace) {
        return String.format(FORMAT, workSpace, name);
    }

    private void save(AbstractConfigMap abstractConfigMap, File file) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            mapper.writeValue(file, abstractConfigMap);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public int countByWorkspaceAndName(String workspace, String name) {
        File file = getFile(workspace, name);
        if (file.exists()) {
            return 1;
        }
        return 0;
    }

    private File getFile(String workspace, String name) {
        File dataDir = config.getConfigMap().getDataDir();
        String mapName = getMapName(name, workspace);
        return new File(dataDir, mapName);
    }

    @Override
    public AbstractConfigMap load(String workspace, String name) {
        File file = getFile(workspace, name);
        return read(file);
    }

    @Override
    public List<AbstractConfigMap> list(String workspace, String key) {
        File dataDir = config.getConfigMap().getDataDir();
        File[] files;
        if (StringUtils.isEmpty(key)) {
            files = dataDir.listFiles(new FilenameFilter() {
                @Override
                public boolean accept(File dir, String name) {
                    return name.endsWith(SUFFIX) && name.contains("-");
                }
            });
        } else {
            files = dataDir.listFiles(new FilenameFilter() {
                @Override
                public boolean accept(File dir, String name) {
                    return name.endsWith(SUFFIX) && name.contains("-") && name.contains(key);
                }
            });
        }
        if (files == null || files.length == 0) {
            return Collections.emptyList();
        }
        List<AbstractConfigMap> result = new ArrayList<>(files.length);
        for (File file : files) {
            result.add(read(file));
        }
        return result;
    }

    @Override
    public void delete(AbstractConfigMap map) {
        File file = getFile(map.getWorkSpace(), map.getName());
        FileUtils.delete(file);
    }

    private AbstractConfigMap read(File file) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            return mapper.readValue(file, AbstractConfigMap.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
